<?php

namespace Common\Model;

/**
 * AppbaseModel 模型基类
 * 
 * 建议方法规范：
 *  get_paging_list, get_scope_fields
 *  item_save, item_delete
 *  refresh_cache
 * 
 * @author Su 2015-3-18 by sutroon
 * @since 1.1 <2015-4-23> SoChishun 从项目中分离到Common\Model
 * @since 1.2 <2015-6-19> SoChishun 新增$autoCheckFields默认字段(false),防止调用D('Common')的时候出错
 */
class CommonModel extends \Think\Model {

    // 不要检测字段
    protected $autoCheckFields = false;

    // 批量验证
    protected $patchValidate = true;

    public function __construct($connection = '') {
        parent::__construct('', '', $connection);
    }

    /**
     * 返回数组消息
     * @param mixed $status 数据库执行结果
     * @param mixed $info 错误消息
     * @return array array('status'=>false, 'info'=>'消息') 或 array('status'=>false, 'info'=>$result)
     * @since 1.0 <2015-3-26> SoChishun Added.
     * @since 2.0 <2015-6-10> SoChishun base_return_array() 重命名为 returnMsg()
     */
    protected function returnMsg($status, $info = false) {
        if (FALSE === $status || is_null($status)) {
            $msg = array('status' => false, 'info' => ($info ? $info : $this->getDbError()));
        } else {
            // 如果status是id值则info=status,否则info=info
            $msg = array('status' => true, 'info' => (true === $status ? $info : $status));
        }
        return $msg;
    }

    /**
     * 分页
     * @param string $pager 分页条字符串变量
     * @param array $options 数据库查询配置,默认array('field' => '*', 'order' => 'id desc', 'group' => null, 'table' => null, 'cache' => 10);
     * @param array $paging_options 分页配置,默认array('page_size' => C('USER.PAGE_SIZE'), 'page_params' => null);
     * @return false|array
     * @since 1.0 <2015-3-5> by sutroon
     * @since 1.1 <2015-4-23> SoChishun $options新增TABLE选项,支持视图查询
     * @since 1.2 <2015-4-24> SoChishun $options新增GROUPBY选项,支持联合查询;新增CACHE选项,支持缓存
     * @since 1.3 <2015-10-26> SoChishun 新增Addon支持
     * @since 2.0 <2015-11-13> SoChishun 重构
     * @since 2.1 <2016-5-6> SoChishun 修改page_size参数
     */
    public function get_paging_list(&$pager, $options = array(), $paging_options = array()) {
        $def_options = array('field' => '*', 'order' => 'id desc', 'table' => $this->tableName);
        $def_paging = array('page_size' => C('LIST_ROWS'), 'page_params' => '');
        $options = array_merge($def_options, $options);
        $paging_options = array_merge($def_paging, $paging_options);
        if (empty($paging_options['page_size'])) {
            $paging_options['page_size'] = 25;
        }
        $table = empty($options['table']) ? FALSE : $options['table'];
        if (empty($options['where'])) {
            $count = $table ? $this->table($table)->count() : $this->count();
        } else {
            $count = $table ? $this->table($table)->where($options['where'])->count() : $this->where($options['where'])->count();
        }
        // 2015-10-26 SoChishun 新增Addon支持
        if (defined('ADDON_NAME') && ADDON_NAME) {
            $paging_options['page_params']['addon'] = ADDON_NAME;
        }
        $page = new \Think\Page($count, $paging_options['page_size'], $paging_options['page_params']);
        $page->setConfig('header', '<span class="rows">每页 ' . $paging_options['page_size'] . ' 条,共 %TOTAL_ROW% 条记录,页次: %NOW_PAGE%/%TOTAL_PAGE%</span>');
        $page->setConfig('theme', '%FIRST% %UP_PAGE% %LINK_PAGE% %DOWN_PAGE% %END% %HEADER%');
        $pager = $page->show();
        if ($page->listRows) {
            $options['limit'] = $page->firstRow . ',' . $page->listRows;
        }
        return $this->select($options);
    }

    /**
     * 返回分页记录列表
     * @param array $where 查询条件
     * @param string $pager 分页条字符串
     * @param array $options 控制选项
     * @return false|array 成功则返回array,否则返回false
     * @since 1.0 <2015-3-5> by sutroon
     * @since 1.1 <2015-4-23> SoChishun $options新增TABLE选项,支持视图查询
     * @since 1.2 <2015-4-24> SoChishun $options新增GROUPBY选项,支持联合查询;新增CACHE选项,支持缓存
     * @since 1.3 <2015-10-26> SoChishun 新增Addon支持
     * @example 
     *      get_paging_list($where, $show, array('ORDERBY' => 'siteID'));
     *      get_paging_list($where, $show, array('PAGEPARAMS' => $search, 'TABLE' => 'vcti_daybill'));
     *      get_paging_list($where, $show, array('FIELDS' => 'tcti_voice_menu.*, tgeneral_file.dirName', 'ORDERBY' => 'tcti_voice_menu.siteID','TABLE'=>'tcti_voice_menu left join tgeneral_file on tcti_voice_menu.music=tgeneral_file.fileName','GROUPBY'=>'tcti_voice_menu.id'));
     */
    public function get_paging_list2($where, &$pager, $options = array()) {
        $options = array_merge(array('PAGESIZE' => C('USER.PAGE_SIZE'), 'FIELDS' => '*', 'ORDERBY' => 'id desc', 'GROUPBY' => null, 'PAGEPARAMS' => null, 'TABLE' => null, 'CACHE' => false), $options);
        $table = $options['TABLE'] ? $options['TABLE'] : FALSE;
        if ($where) {
            $count = $table ? $this->table($table)->where($where)->count() : $this->where($where)->count();
        } else {
            $count = $table ? $this->table($table)->count() : $this->count();
        }
        // 2015-10-26 SoChishun 新增Addon支持
        if (defined('ADDON_NAME') && ADDON_NAME) {
            $options['PAGEPARAMS']['addon'] = ADDON_NAME;
        }
        $page = new \Think\Page($count, $options['PAGESIZE'], $options['PAGEPARAMS']);
        $pager = $page->show();
        $params['where'] = $where;
        if ('*' != $options['FIELDS']) {
            $params['field'] = $options['FIELDS'];
        }
        if ($options['ORDERBY']) {
            $params['order'] = $options['ORDERBY'];
        }
        if ($options['GROUPBY']) {
            $params['group'] = $options['GROUPBY'];
        }
        if ($options['CACHE']) {
            $params['cache'] = $options['CACHE'];
        }
        if ($table) {
            $params['table'] = $table;
        }
        if ($page->listRows) {
            $params['limit'] = $page->firstRow . ',' . $page->listRows;
        }
        return $this->select($params);
    }

    /**
     * 返回树形列表或刷新缓存
     * 
     * @param string $scope 命名范围,一般为treeselect或treetable
     * @param array $checked_ids
     * @since 1.0 <2015-3-25> SoChishun Added.
     * @since 2.0 <2015-10-22> SoChishun 重构,把参数整合成$select_options,$data-options
     * @since 2.1 <2015-10-26> SoChishun 新增where条件数组限制,比较规范
     * @example return $this->base_get_tree_list('Role/' . $scope, $scope,$refresh);
     */
    public function base_get_tree_list($select_options = array(), $data_options = array()) {
        if (!empty($data_options['CHECKED_IDS']) && !is_array($data_options['CHECKED_IDS'])) {
            $data_options['CHECKED_IDS'] = explode(',', $data_options['CHECKED_IDS']);
        }
        if (!empty($data_options['FIRST_WHERE']) && !is_array($data_options['FIRST_WHERE'])) {
            throw new \Exception('[TREE]FIRST_WHERE不是有效数组!');
        }
        if (!empty($select_options['where']) && !is_array($select_options['where'])) {
            throw new \Exception('[TREE]WHERE不是有效数组!');
        }
        $_data_options = array('CHECKED_IDS' => array(), 'PID' => 0, 'PID_FIELD' => 'pid', 'FIRST_WHERE' => '', 'CHILDREN_KEY' => 'children');
        $data_options = array_merge($_data_options, $data_options);
        return $this->base_get_tree_list_fn($select_options, $data_options);
    }

    /**
     * 返回树形列表的子方法
     * @param string $scope
     * @param array $checked_ids
     * @param int $fid
     * @param string $first_where
     * @param string $children_key
     * @return false|array
     * @since 1.0 <2015-3-25> SoChishun Added.
     * @since 1.1 <2015-7-31> SoChishun 新增$children_key参数
     * @since 2.0 <2015-10-22> SoChishun 重构,把参数整合成$select_options,$data-options
     * @example $list = $this->get_tree_list_fn('main_nav', 0,$where_lv0);
     */
    function base_get_tree_list_fn($select_options = array(), $data_options = array()) {
        if (empty($select_options['where'])) {
            $select_options['where'] = array($data_options['PID_FIELD'] => $data_options['PID']);
            if (!empty($data_options['FIRST_WHERE'])) {
                $select_options['where'] = array_merge($select_options['where'], $data_options['FIRST_WHERE']);
            }
        }
        $list = $this->select($select_options);
        $new_list = false;
        if ($list) {
            foreach ($list as $row) {
                $where2 = array_merge($select_options, array('where' => array($data_options['PID_FIELD'] => $row['id'])));
                $row[$data_options['CHILDREN_KEY']] = $this->base_get_tree_list_fn($where2, $data_options);
                $row['checked'] = 'False';
                if (!empty($data_options['CHECKED_IDS']) && in_array($row['id'], $data_options['CHECKED_IDS'])) {
                    $row['checked'] = 'True';
                }
                $new_list[] = $row;
            }
        }
        return $new_list;
    }

    /**
     * 获取系统扩展字段列表
     * @param string $target 关联对象,如 CUSTOMER、PRODUCT
     * @param int $siteID siteID
     * @return false|array
     * @since 1.0 2014-12-13 by sutroon
     * @example $list = sofunc_get_sys_exfield_list('CUSTOMER', $siteID);
     */
    function sofunc_get_sys_exfield_list($target, $siteID, $display = 1) {
        $where['target'] = $target;
        $where['siteID'] = $siteID;
// $where['isDisplay'] = $display;
        return M('tsys_exfield')->field('`field`, `type`, `length`, `default`, label, inputType, optionalValue, isRequire')->where($where)->order('ordinal, id')->select();
    }

    /**
     * 获取系统扩展字段单条记录数据
     * @param string $target 关联对象,如 CUSTOMER、PRODUCT
     * @param int $siteID siteID
     * @param int $itemID 项目编号
     * @return false|array 成功则返回数组,否则返回false
     * @since 1.0 2014-12-15 by sutroon
     * @example $data = sofunc_get_sys_exfield_data($target, $siteID, $itemID);
     */
    function sofunc_get_sys_exfield_data($target, $siteID, $itemID) {
        switch ($target) {
            case 'CUSTOMER':
                return M('tcustomer_ex_' . $siteID)->where("userID=$itemID")->find();
            case 'PRODUCT':
                return M('tproduct_ex_' . $siteID)->where("productID=$itemID")->find();
                break;
            default:
                return false;
        }
    }

    /**
     * 获取规范的Url参数sort
     * <br />如: $sortby = sofunc_get_orderby(I('sort'))
     * @param string $sort
     * @return boolean
     * @since 1.0 2015-2-2 by sutroon
     */
    function sofunc_get_orderby($sort) {
        if ($sort) {
            switch ($sort[0]) {
                case 'D':
                    return substr($sort, 1) . ' DESC';
                case 'A':
                    return substr($sort, 1);
                default:
                    return $sort;
            }
        }
        return false;
    }

    /**
     * 查询树形列表并分页
     * @param string $table 数据表名称
     * @param string $where 查询条件
     * @param string $strpage 分页条
     * @param int $parentID 父级编号
     * @param array $options 可选参数,包含 int:PAGESIZE, string:FIELDS, string:ORDERBY, array:PAGEPARAMS
     * @return array
     * @since 1.0 2014-8-21 by sutroon
     */
    function sofunc_get_paging_tree($table, $where, &$strpage, $parentID = 0, $options = array()) {
        $options = array_merge(array('PAGESIZE' => C('USR_PAGESIZE'), 'FIELDS' => '*', 'ORDERBY' => 'id', 'PAGEPARAMS' => null), $options);
        $orderby = $options['ORDERBY'] ? ' order by ' . $options['ORDERBY'] : '';
        $search = is_array($where) ? sofunc_convert_array_search_to_string($where) : $where;
        if ($search) {
            $search = ' where ' . str_replace('{0}', $parentID, $search);
        }
        $M = M();
        $list = $M->query("select count(" . $options['FIELDS'] . ") as n from $table $search");
        $count = $list[0]['n'];

        $Page = create_page($count, $options['PAGESIZE'], is_array($options['PAGEPARAMS']) ? $options['PAGEPARAMS'] : sofunc_convert_tpexp_to_querystring($where));
        $strpage = $Page->show();

        $list = $M->query('select ' . $options['FIELDS'] . " from $table $search $orderby limit " . $Page->firstRow . ',' . $Page->listRows);
        $arr = array();
        if ($list) {
            foreach ($list as $row) {
                $row['treeLevel'] = 1;
                $arr[] = $row;
                func_sofunc_get_paging_tree($table, $options['FIELDS'], $orderby, $row['id'], $arr, 2);
            }
        }
        return $arr;
    }

// 2014-8-21 by sutroon
    function func_sofunc_get_paging_tree($table, $fields, $orderby, $parentID, &$arr, $n = 1) {
        $list = M()->query('select ' . $fields . " from $table where parentID=" . $parentID . $orderby);
        if ($list) {
            foreach ($list as $row) {
                $row['treeLevel'] = $n;
                $arr[] = $row;
                func_sofunc_get_paging_tree($table, $fields, $orderby, $row['id'], $arr, $n + 1);
            }
        }
    }

    /**
     * 获取树形数据表
     * @param string $table 数据表名称
     * @param string $where 查询条件,占位符{0},如: parentID={0} and name like '%abc%'
     * @param int $parentID 父级编号,默认是0
     * @param array $options 可选参数, 包含: string:FIELDS, string:ORDERBY
     * @return array 返回包含sub子数组的数组
     * @since 1.0 2014-10-28 by sutroon
     * @example sofunc_get_tree_table('tuser_permission', "parentID={0}", 0, array('ORDERBY' => 'id asc'));
     */
    function sofunc_get_tree_table($table, $where = 'parentID={0}', $parentID = 0, $options = array()) {
        $opts = array('FIELDS' => '*', 'ORDERBY' => 'id');
        if ($options) {
            $opts = array_merge($opts, $options);
        }
        $orderby = $options['ORDERBY'] ? ' order by ' . $opts['ORDERBY'] : '';
        $search = is_array($where) ? sofunc_convert_array_search_to_string($where) : $where;
        if ($search) {
            $search = ' where ' . str_replace('{0}', $parentID, $search);
        }
        $list = M()->query('select ' . $opts['FIELDS'] . " from $table $search $orderby");
        $arr = array();
        if ($list) {
            foreach ($list as $row) {
                $row['sub'] = sofunc_get_tree_table($table, $where, $row['id'], $options);
                $arr[] = $row;
            }
        }
        return $arr;
    }

}
